#!/usr/bin/env python
# -*- coding: utf8 -*-
import mediawiki, re, time
from google.appengine.api import memcache

class BlueLinkHandler:
    def __init__(self):
        self.site = mediawiki.login()
        self.pgtitles = []
        _allowlangs = ['ar', 'de', 'en', 'es', 'fi', 'fr', 'it', 'ja', 'nl',
                      'no', 'pl', 'pt', 'ru', 'sv', 'ko', 'vi', 'tr']
        _linkpattern = '(\{\{\s*(?:'
        _allowlang1 = '|'.join(_allowlangs)
        _allowlang2 = '|'.join(['[' + _al[0].upper() + _al[0] + ']'+ _al[1:] for _al in _allowlangs])
        _linkpattern += '[Ii]nternal[_ ]link[_ ]helper/(?:%s)' % _allowlang1
        _linkpattern += '|[Ll]ink-(?:%s)' % _allowlang1
        _linkpattern += '|(?:%s)-link' % _allowlang2
        _linkpattern += ')\s*\|\s*([^\|]+?)\s*\|\s*([^\|]+?)\s*(?:\|\s*([^\|]+?)\s*)?\}\})'
        self._linkreg = re.compile(_linkpattern)

    def getPageTitles(self):
        self.pgtitles = memcache.get('pgtitles')
        reset = memcache.get('reset')
        if self.pgtitles == None or reset == None:
            self.pgtitles = self.site.categoryMembers(u'有蓝链却未移除内部链接助手模板的页面',
                                                      ns = [0, 4, 6, 10, 12, 14, 100])
            memcache.set('reset', True, 21600)
            self.savePageTitles()

    def savePageTitles(self):
        return memcache.set('pgtitles', self.pgtitles)

    def processOne(self):
        if self.pgtitles:
            pgtitle = self.pgtitles.pop(0)
        else:
            return 'END'
        for _i in range(0, 5):
            try:
                ret = self._processing(pgtitle)
                return ret
            except:
                return False

    def _processing(self, pgtitle):
        page = self.site(pgtitle)
        content = page.recentRevision.content
        possiblelinktitles = self._retrievePossibleLinkTitles(content)
        possiblelinks = [_l for (_l, _t) in possiblelinktitles]
        bluelinks = []
        if possiblelinks:
            bluelinks = self.site.isExists(possiblelinks)
        if bluelinks:
            summary = u'机器人：清理蓝链条目'
            newcontent = self._replaceContent(content, bluelinks)
            rev = mediawiki.Revision(newcontent, summary, bot = True)
            try:
                page.appendRevision(rev)
            except mediawiki.PageNotSaved:
                return False
            return True
        else:
            return False

    def _replaceContent(self, content, links):
        return self._linkreg.sub(lambda m: self._replaceHandler(m, links), content)

    def _replaceHandler(self, m, links):
        _g = m.groups()
        (_l, _t) = self._getParams((_g[1], _g[2], _g[3]))
        if _l in links:
            if _t:
                return '[[%s|%s]]' % (_l, _t)
            else:
                return '[[%s]]' % _l
        else:
            return _g[0]

    def _retrievePossibleLinkTitles(self, content):
        _links = self._linkreg.findall(content)
        if not _links:
            return []
        ret = []
        for _g in _links:
            (link, title) = self._getParams((_g[1], _g[2], _g[3]))
            if link:
                ret.append((link, title))
        return ret

    def _getParams(self, group):
        param_1 = '' # link
        param_1_fix = False # specified by param 1
        param_3 = '' # title
        param_3_fix = False # specified by param 3
        _count = 0
        for info in group:
            if not info:
                info = ''
            sep = info.split('=', 1)
            if len(sep) == 2:
                if sep[0].strip() == '1':
                    param_1 = sep[1].strip()
                    param_1_fix = True
                elif sep[0].strip() == '3':
                    param_3 = sep[1].strip()
                    param_3_fix = True
            elif len(sep) == 1:
                if _count == 0:
                    if param_1_fix:
                        _count = 1 # pass
                    else:
                        param_1 = sep[0]
                elif _count == 2:
                    if param_3_fix:
                        _count = 3 # pass
                    else:
                        param_3 = sep[0]
                _count += 1
        return (param_1, param_3)

def main():
    handler = BlueLinkHandler()
    handler.getPageTitles()
    starttime = time.time()
    while True:
        if handler.processOne() != 'END':
            handler.savePageTitles()
            now = time.time()
            if now - starttime > 25:
                break
        else:
            break
    

if __name__ == '__main__':
    main()